#include "factory.h"

int exit_fds[2];//传递退出机制的信号
//退出机制的处理函数
void sig_exit_func(int signum)
{
    write(exit_fds[1],&signum,1);
}

int main(int argc,char *argv[])
{
    ARGS_CHECK(argc,5);
    pipe(exit_fds);
    if(fork())
    {//父进程用于进程的退出机制
        close(exit_fds[0]);
        signal(SIGUSR1,sig_exit_func);
        wait(NULL);
        return 0;
    }
    close(exit_fds[1]);
    Factory_t f;//线程只能传递一个指针，定义一个数据结构包含需要传的参数更方便
    int thread_num=atoi(argv[3]);
    int capacity=atoi(argv[4]);
    factory_init(&f,thread_num,capacity);
    factory_start(&f,thread_num);
    int socket_fd;
    tcp_init(&socket_fd,argv[1],argv[2]);
    int new_fd;
    struct sockaddr_in cli_addr;
    pNode_t pnew;
    //生成一个指向队列的指针
    pQue_t pq=&f.que;
    int epfd=epoll_create(1);
    epoll_add(epfd,socket_fd);
    epoll_add(epfd,exit_fds[0]);
    struct epoll_event evs[2];
    int ready_num,i,j;
    while(1)
    {
        ready_num=epoll_wait(epfd,evs,2,-1);
        for(i=0;i<ready_num;i++)
        {//此时有客户端连接，主线程将其分给进程池
            if(evs[i].data.fd==socket_fd)
            {
                bzero(&cli_addr,sizeof(cli_addr));
                socklen_t addr_len=sizeof(cli_addr);
                new_fd=accept(socket_fd,(struct sockaddr *)&cli_addr,&addr_len);
                printf("%s %d is connect\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
                pnew=(pNode_t)calloc(1,sizeof(Node_t));
                pnew->new_fd=new_fd;
                //先给任务队列加锁后把任务放入队列，并且唤醒线程池
                pthread_mutex_lock(&pq->mutex);
                que_set(pq,pnew);
                pthread_mutex_unlock(&pq->mutex);
                pthread_cond_signal(&f.cond);
            }
            if(evs[i].data.fd==exit_fds[0])
            {//此时收到退出信号
                for(j=0;j<thread_num;j++)
                {
                    pthread_cancel(f.pthid[j]);
                    printf("thread j cancel success\n");
                }
                for(j=0;j<thread_num;j++)
                {
                    pthread_join(f.pthid[j],NULL);
                }
                exit(0);
            }
        }
    }
    return 0;
}